package com.sec.etech.file.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sec.etech.file.dto.FileUploadDTO;
import com.sec.etech.file.mapper.EtechFileMapper;
import com.sec.etech.file.model.EtechFile;
import com.sec.etech.file.model.EtechFileTemp;
import com.sec.etech.sys.util.DbUtil;
import org.openbpm.base.api.exception.BusinessMessage;
import org.openbpm.base.core.id.IdUtil;
import org.openbpm.base.core.util.StringUtil;
import org.openbpm.sys.upload.IUploader;
import org.openbpm.sys.upload.UploaderFactory;
import org.openbpm.sys.util.ContextUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class EtechWebUploaderService {
    @Resource
    EtechFileTempService etechFileTempService;

    @Resource
    EtechFileHandlerService etechFileHandlerService;

    @Resource
    private EtechFileMapper etechFileMapper;

    @Resource
    EtechOrdinaryUploader etechOrdinaryUploader;

    /**
     * 上传文件到临时文件表
     * 支持分片上传
     *
     * @param fileUploadDTO
     * @return
     */
    public JSONObject upload(FileUploadDTO fileUploadDTO) {
        InputStream is = null;

        try {
            is = fileUploadDTO.getFile().getInputStream();
            String relativePath = "";
            //判断是否分片
            if (fileUploadDTO.getChunks() != null && fileUploadDTO.getChunk() != null) {
                //分片上传文件
                relativePath = uploadChunkFileToTemp(is, fileUploadDTO);
            } else {
                String id = IdUtil.getSuid();
                relativePath = saveFileToTemp(is, id + "." + FileUtil.extName(fileUploadDTO.getName()));
                EtechFileTemp etechFileTemp = saveTempFile(id, relativePath, fileUploadDTO);
                return JSONUtil.parseObj(etechFileTemp);
            }
            fileUploadDTO.setRelativePath(relativePath);
            fileUploadDTO.setFile(null);
            return JSONUtil.parseObj(fileUploadDTO);
        } catch (IOException e) {
            throw new BusinessMessage("文件上传失败，{}", e);
        } finally {
            IoUtil.close(is);
        }
    }

    /**
     * 保存文件到临时文件夹
     *
     * @param is
     * @param fileName
     * @return 返回相对路径
     */
    public String saveFileToTemp(InputStream is, String fileName) {
        String relativePath = etechFileHandlerService.getTempFileRelativePath(fileName);
        String absPath = etechFileHandlerService.getAbsolutePath(relativePath);
        if (!FileUtil.exist(new File(absPath).getParentFile())) {
            FileUtil.mkParentDirs(absPath);
        }
        FileUtil.writeFromStream(is, absPath);
        return relativePath;
    }

    /**
     * 分片上传文件到临时文件夹
     *
     * @param is
     * @param fileUploadDTO
     * @return 返回相对路径
     */
    public String uploadChunkFileToTemp(InputStream is, FileUploadDTO fileUploadDTO) {
        String relativePath = etechFileHandlerService.getTempFileRelativePath(fileUploadDTO.getGuid());
        String absPath = etechFileHandlerService.getAbsolutePath(relativePath) + File.separator + fileUploadDTO.getChunk();
        File file = FileUtil.file(absPath);
        if (FileUtil.exist(file) && fileUploadDTO.getFile().getSize() == FileUtil.size(file)) {
            //文件已经存在说明分片已经上传过了，且大小一致，直接返回
            return relativePath;
        }
        if (!FileUtil.exist(new File(absPath).getParentFile())) {
            FileUtil.mkParentDirs(absPath);
        }
        FileUtil.writeFromStream(is, absPath);
        return relativePath;
    }

    /**
     * 分片文件合并
     *
     * @param fileUploadDTO
     * @return
     */
    public EtechFileTemp merge(FileUploadDTO fileUploadDTO) throws FileNotFoundException {
        String ext = FileUtil.extName(fileUploadDTO.getName());
        String id = IdUtil.getSuid();
        //合并文件
        String baseDir = etechFileHandlerService.getEtechFileBaseDir();
        File file = new File(baseDir + fileUploadDTO.getRelativePath());
        File newFile = new File(FileUtil.getParent(baseDir + fileUploadDTO.getRelativePath(), 1) + File.separator + id + "." + ext);
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files != null && files.length > 0 && fileUploadDTO.getChunks() == files.length) {
                for (int i = 0; i < files.length; i++) {
                    InputStream is = FileUtil.getInputStream(baseDir + fileUploadDTO.getRelativePath() + File.separator + i);
                    FileOutputStream destTempfos = new FileOutputStream(newFile, true);
                    IoUtil.copy(is, destTempfos);
                    IoUtil.close(is);
                    IoUtil.close(destTempfos);
                }
                //合并完毕后检查文件大小是否一致
                if (fileUploadDTO.getSize() != FileUtil.size(newFile)) {
                    throw new BusinessMessage("分片文件合并出错，文件大小不一致!");
                }
                FileUtil.del(file);
            } else {
                //分片数必须等于文件夹内的文件数
                throw new BusinessMessage("分片文件合并出错，文件数据不完整!");
            }
        }

        String newPath = fileUploadDTO.getRelativePath().replaceFirst(fileUploadDTO.getGuid(), id + "." + ext);
        //更新到临时表数据库
        return saveTempFile(id, newPath, fileUploadDTO);
    }


    /**
     * 保存临时文件表数据
     *
     * @param id
     * @param path
     * @param fileUploadDTO
     * @return
     */
    public EtechFileTemp saveTempFile(String id, String path, FileUploadDTO fileUploadDTO) {
        EtechFileTemp etechFileTemp = new EtechFileTemp();
        // 上传器区分旧的
        String uploader = "etech-web-uploader";
        etechFileTemp.setUploader(uploader);
        etechFileTemp.setId(id);
        etechFileTemp.setName(fileUploadDTO.getName());
        if (StrUtil.isBlank(fileUploadDTO.getModule())) {
            //默认etech
            fileUploadDTO.setModule("etech");
        }
        etechFileTemp.setModule(fileUploadDTO.getModule());
        if (StrUtil.isBlank(fileUploadDTO.getUniqueIdentifier())) {
            fileUploadDTO.setUniqueIdentifier(id);
        }
        etechFileTemp.setUniqueIdentifier(fileUploadDTO.getUniqueIdentifier());
        //更改路径文件名称
        if (StrUtil.isNotBlank(fileUploadDTO.getGuid()) && path.indexOf(fileUploadDTO.getGuid()) > -1) {
            path = path.replaceFirst(fileUploadDTO.getGuid(), id + "." + FileUtil.extName(path));
        }
        etechFileTemp.setPath(path);
        etechFileTemp.setMd5(fileUploadDTO.getMd5());

        etechFileTemp.setFileVersion("00");
        //判断版本
        if (!id.equalsIgnoreCase(fileUploadDTO.getUniqueIdentifier())) {
            String sql = "select max(file_version_) version from sys_file where (delete_=0 or delete_ is null) and unique_identifier_=?";
            List<Map<String, Object>> list = DbUtil.getJdbcTemplate().queryForList(sql, fileUploadDTO.getUniqueIdentifier());
            if (CollUtil.isNotEmpty(list) && list.get(0).get("version") != null) {
                etechFileTemp.setFileVersion(String.format("%02d", Integer.parseInt(list.get(0).get("version").toString()) + 1));
            }
        }


        etechFileTemp.setFileType(FileUtil.extName(fileUploadDTO.getName()));
        etechFileTemp.setFileMime(FileUtil.getMimeType(fileUploadDTO.getName()));
        etechFileTemp.setFileLength(fileUploadDTO.getSize());
        etechFileTemp.setLatest(1);

        Date date = new Date();
        etechFileTemp.setYear(DateUtil.year(date));
        etechFileTemp.setCreateTime(date);
        etechFileTemp.setUpdateTime(date);
        etechFileTemp.setCreateBy(ContextUtil.getCurrentUserId());
        etechFileTemp.setUpdateBy(ContextUtil.getCurrentUserId());

        etechFileTempService.save(etechFileTemp);
        return etechFileTemp;
    }
    public String saveOrUpdateTempFile(com.alibaba.fastjson.JSONObject object) {
        if(StringUtil.isEmpty(object.getString("id"))){
            return saveTempFile(object);
        }else {
            EtechFileTemp temp = etechFileTempService.getById(object.getString("id"));
            if(temp==null){
                saveTempFile(object);
            }else{
                updateTempFile(object);
            }
            return object.getString("id");
        }
    }
    public boolean updateTempFile(com.alibaba.fastjson.JSONObject object) {
        EtechFileTemp etechFileTemp = com.alibaba.fastjson.JSONObject.toJavaObject(object, EtechFileTemp.class);
        etechFileTemp.setId(object.getString("id"));
        etechFileTemp.setUploader("etech-web-uploader");
        String path = etechFileTemp.getPath();
        etechFileTemp.setPath(StringUtil.isNotEmpty(path)? path.replaceAll("\\\\", "/"): path);
        etechFileTemp.setPreviewPath(this.getPreviewPath(etechFileTemp.getPath(), etechFileTemp.getPreviewPath()));
        return etechFileTempService.updateById(etechFileTemp);
    }
    //保存临时文件
    public String saveTempFile(com.alibaba.fastjson.JSONObject object) {
        EtechFileTemp etechFileTemp = com.alibaba.fastjson.JSONObject.toJavaObject(object, EtechFileTemp.class);
        String baseDir = etechFileHandlerService.getEtechFileBaseDir();
        if(StringUtil.isEmpty(etechFileTemp.getPath()) && StringUtil.isEmpty(etechFileTemp.getPreviewPath())){
            return null;
        }
        etechFileTemp.setUploader("etech-web-uploader");
        if (StrUtil.isBlank(etechFileTemp.getModule())) {
            //默认etech
            etechFileTemp.setModule("etech");
        }
        if(StringUtil.isEmpty(etechFileTemp.getFileVersion())) {
            etechFileTemp.setFileVersion("00");
        }
        String tempPath = etechFileTemp.getPath();
        if(StringUtil.isNotEmpty(tempPath)){
            tempPath = tempPath.replaceAll("\\\\", "/");
            etechFileTemp.setPath(tempPath);
        }else {
            etechFileTemp.setPreviewPath(this.getPreviewPath(etechFileTemp.getPath(), etechFileTemp.getPreviewPath()));
            tempPath = etechFileTemp.getPreviewPath();
        }
        File tempFile = FileUtil.file(baseDir + tempPath);
        etechFileTemp.setFileLength(tempFile.length());
        etechFileTemp.setFileType(tempPath.substring(tempPath.lastIndexOf(".") + 1));
        etechFileTemp.setLatest(1);

        /*if(etechFileTemp.getId()==null){
            int index = tempPath.lastIndexOf("/");
            String id = tempPath.substring(index + 1).split("\\.")[0];
            if(id.endsWith("_p")){
                etechFileTemp.setId(id.substring(0, id.length()-2));
            }
        }
        if(etechFileTemp.getUniqueIdentifier()==null){
            etechFileTemp.setUniqueIdentifier(etechFileTemp.getId());
        }*/
        if(etechFileTemp.getId()==null) {
            etechFileTemp.setId(IdUtil.getSuid());
        }
        Date date = new Date();
        etechFileTemp.setYear(DateUtil.year(date));
        etechFileTemp.setCreateTime(date);
        etechFileTemp.setUpdateTime(date);
        etechFileTemp.setCreateBy(ContextUtil.getCurrentUserId());
        etechFileTemp.setUpdateBy(ContextUtil.getCurrentUserId());
        etechFileTempService.save(etechFileTemp);
        return etechFileTemp.getId();
    }
    //临时文件表迁移到正式文件表（包含文件迁移）
    public String moveTempFileOrUpdateFile(EtechFileTemp etechFileTemp) {
        String fileId = null;
        if(etechFileTemp.getId()!=null){
            String baseDir = etechFileHandlerService.getEtechFileBaseDir();
            EtechFile etechFile = etechFileMapper.selectById(etechFileTemp.getId());
            if(etechFile!=null) {
                String path = etechFileTemp.getPath();
                if (!FileUtil.exist(baseDir + path)) {
                    throw new BusinessMessage("临时文件不存在或者已删除！fileId=" + etechFileTemp.getId());
                }
                if (StrUtil.isBlank(etechFileTemp.getModule())) {
                    //模块默认etech
                    etechFileTemp.setModule("etech");
                }
                etechFile.setName(etechFileTemp.getName());
                etechFile.setModule(etechFileTemp.getModule());
                File tempFile = FileUtil.file(baseDir + path);
                if (path.startsWith("temp")) {
                    path = path.replaceFirst("temp", etechFileTemp.getModule());
                }
                etechFile.setPath(path.replaceAll("\\\\", "/"));
                if(etechFileTemp.getFileLength()==null || etechFileTemp.getFileLength()==0){//文件大小
                    etechFile.setFileLength(tempFile.length());
                }else {
                    etechFile.setFileLength(etechFileTemp.getFileLength());
                }
                if(StringUtil.isEmpty(etechFileTemp.getFileType())) {//文件类型
                    etechFile.setFileType(path.substring(path.lastIndexOf(".") + 1));
                }else {
                    etechFile.setFileType(etechFileTemp.getFileType());
                }
                String previewPath = etechFileTemp.getPreviewPath();
                File previewFile = null;
                if (StringUtil.isNotEmpty(previewPath)) {
                    previewFile = FileUtil.file(baseDir + previewPath);
                    if (previewPath.startsWith("temp")) {
                        previewPath = previewPath.replaceFirst("temp", etechFileTemp.getModule());
                    }
                    etechFile.setPreviewPath(previewPath.replaceAll("\\\\", "/"));
                }
                if(StringUtil.isNotEmpty(etechFileTemp.getFileVersion())){//默认版本00
                    etechFile.setFileVersion(etechFileTemp.getFileVersion());
                }
                if(StringUtil.isNotEmpty(etechFileTemp.getUniqueIdentifier())){
                    etechFile.setUniqueIdentifier(etechFileTemp.getUniqueIdentifier());
                }
                if(etechFile.getUpdateTime()==null){
                    etechFile.setUpdateTime(new Date());
                }
                if(etechFile.getUpdateBy()==null){
                    etechFile.setUpdateBy(ContextUtil.getCurrentUserId());
                }
                if (etechFileMapper.updateById(etechFile) > 0) {
                    //更新其他版本的最新数据为旧版
                    if (etechFileTemp.getId()!=null && !etechFileTemp.getId().equalsIgnoreCase(etechFile.getUniqueIdentifier())) {
                        etechFileMapper.update(null, Wrappers.<EtechFile>lambdaUpdate()
                                .eq(EtechFile::getUniqueIdentifier, etechFile.getUniqueIdentifier())
                                .eq(EtechFile::getLatest, 1)
                                .ne(EtechFile::getId, etechFile.getId())
                                .set(EtechFile::getLatest, 0)
                        );
                    }
                    //保存成功后再移动文件
                    FileUtil.move(tempFile, FileUtil.file(baseDir + path), true);
                    tempFile.delete();//删除临时文件
                    //保存成功后再移动预览文件
                    if(previewFile!=null) {
                        FileUtil.move(previewFile, FileUtil.file(baseDir + previewPath), true);
                        previewFile.delete();//删除临时文件
                    }
                    if(etechFileTemp.getId()!=null) {
                        //移动成功后删除临时表
                        etechFileTempService.removeById(etechFileTemp.getId());
                    }
                    fileId = etechFile.getId();
                }
            }else {
                fileId = this.moveTempFileToFormalFile(etechFileTemp);
            }
        }
        return fileId;
    }
    //从临时文件夹移动到正式文件夹
    public String moveTempFileOnly(String tempFileId, String tempFilePath, String filePath) {
        if(StringUtil.isEmpty(filePath)){
            throw new BusinessMessage("目标文件路径不存在或者已删除！filePath=" + filePath);
        }
        String baseDir = etechFileHandlerService.getEtechFileBaseDir(tempFilePath);
        File tempFile = new File(baseDir + tempFilePath);
        if (!tempFile.exists()) {
            throw new BusinessMessage("临时文件不存在或者已删除！tempFilePath=" + tempFile.getAbsolutePath());
        }
        String length = String.valueOf(tempFile.length());
        baseDir = etechFileHandlerService.getEtechFileBaseDir(filePath);
        FileUtil.move(tempFile, FileUtil.file(baseDir + filePath), true);
        tempFile.delete();
        if(StringUtil.isNotEmpty(tempFileId)) {
            etechFileTempService.removeById(tempFileId);
        }
        return length;
    }
    /**
     * 把文件从一个路径（支持非临时目录）移动到正式路径。
     * srcFilePath：文件绝对路径
     * targetFile：文件相对路径
     */
    public void moveTempFileOnly(String srcFilePath, String targetFile) {
        File srcFile = new File(srcFilePath);
        if (!srcFile.exists()) {
            throw new BusinessMessage("源文件不存在或者已删除！srcFile=" + srcFile.getAbsolutePath());
        }
        String baseDir = etechFileHandlerService.getEtechFileBaseDir(targetFile);
        FileUtil.move(srcFile, FileUtil.file(baseDir + targetFile), true);
        srcFile.delete();
    }
    //复制到临时文件夹
    public String copyEtechFileTempAndUpdateVersion(String fileId, String fileVersion) {
        EtechFile etechFile = etechFileMapper.selectById(fileId);
        String path = etechFile.getPath().replaceAll("\\\\", "/");
        EtechFileTemp newFile = JSONUtil.toBean(JSONUtil.toJsonStr(etechFile), EtechFileTemp.class);;
        newFile.setId(IdUtil.getSuid());
        int index = path.lastIndexOf("/");
        String logicName = path.substring(index + 1).split("\\.")[0];
        newFile.setPath((path.replace(logicName, newFile.getId())).replace(etechFile.getModule(), "temp"));
        newFile.setPreviewPath("");
        newFile.setFileVersion(fileVersion);
        newFile.setYear(DateUtil.year(new Date()));
        newFile.setCreateBy(ContextUtil.getCurrentUserId());
        newFile.setCreateTime(new Date());
        newFile.setUpdateBy(ContextUtil.getCurrentUserId());
        newFile.setUpdateTime(new Date());
        boolean f = etechFileTempService.save(newFile);
        if(f) {//存表成功后复制文件
            String baseDir = etechFileHandlerService.getEtechFileBaseDir();
            FileUtil.copy(baseDir + path, baseDir + newFile.getPath(), true);
        }
        return newFile.getId();
    }
    public EtechFile selectEtechFileById(String fileId) {
        return etechFileMapper.selectById(fileId);
    }
    /**
     * 移动临时文件到正式文件
     *
     * @param etechFileTemp
     */
    @Transactional(rollbackFor = Exception.class)
    public String moveTempFileToFormalFile(EtechFileTemp etechFileTemp) {
        if (etechFileTemp == null) {
            //不存在说明已经移动过了，忽略
            return null;
        }
        String baseDir = etechFileHandlerService.getEtechFileBaseDir();
        String path = etechFileTemp.getPath();
        if (!FileUtil.exist(baseDir + path)) {
            throw new BusinessMessage("临时文件不存在或者已删除！fileId=" + etechFileTemp.getId());
        }
        EtechFile etechFile = JSONUtil.toBean(JSONUtil.toJsonStr(etechFileTemp), EtechFile.class);
        //如果临时文件存在版本以此版本为准
        if(StringUtil.isEmpty(etechFile.getFileVersion())) {
            if (etechFileTemp.getId() != null && !etechFileTemp.getId().equalsIgnoreCase(etechFile.getUniqueIdentifier())) {
                String sql = "select max(file_version_) version from sys_file where (delete_=0 or delete_ is null) and unique_identifier_=?";
                List<Map<String, Object>> list = DbUtil.getJdbcTemplate().queryForList(sql, etechFile.getUniqueIdentifier());
                if (CollUtil.isNotEmpty(list) && list.get(0).get("version") != null) {
                    etechFile.setFileVersion(String.format("%02d", Integer.parseInt(list.get(0).get("version").toString()) + 1));
                }
            }
        }
        File tempFile = FileUtil.file(baseDir + path);
        if (path.startsWith("temp")) {
            path = path.replaceFirst("temp", etechFileTemp.getModule());
        }
        if(etechFile.getFileLength()==null || etechFile.getFileLength()==0){//文件大小
            etechFile.setFileLength(tempFile.length());
        }
        if(StringUtil.isEmpty(etechFile.getFileType())) {//文件类型
            etechFile.setFileType(path.substring(path.lastIndexOf(".") + 1));
        }
        etechFile.setPath(path.replaceAll("\\\\", "/"));
        String previewPath = etechFileTemp.getPreviewPath();
        File previewFile = null;
        if (StringUtil.isNotEmpty(previewPath)) {
            previewFile = FileUtil.file(baseDir + previewPath);
            if (previewPath.startsWith("temp")) {
                previewPath = previewPath.replaceFirst("temp", etechFileTemp.getModule());
            }
            etechFile.setPreviewPath(previewPath);
        }
        if(etechFile.getId()==null){
            String filePath = etechFile.getPath();
            int index = filePath.lastIndexOf("/");
            etechFile.setId(filePath.substring(index + 1).split("\\.")[0]);
        }
        if(StringUtil.isEmpty(etechFile.getFileVersion())){//默认版本00 唯一标识默认ID
            etechFile.setFileVersion("00");
        }
        if(StringUtil.isEmpty(etechFile.getUniqueIdentifier())){
            etechFile.setUniqueIdentifier(etechFile.getId());
        }
        if(etechFile.getCreateTime()==null){
            etechFile.setCreateTime(new Date());
        }
        if(etechFile.getCreateBy()==null){
            etechFile.setCreateBy(ContextUtil.getCurrentUserId());
        }
        if(etechFile.getUpdateTime()==null){
            etechFile.setUpdateTime(new Date());
        }
        if (etechFileMapper.insert(etechFile) > 0) {
            //更新其他版本的最新数据为旧版
            if (etechFileTemp.getId() != null && !etechFileTemp.getId().equalsIgnoreCase(etechFile.getUniqueIdentifier())) {
                etechFileMapper.update(null, Wrappers.<EtechFile>lambdaUpdate()
                        .eq(EtechFile::getUniqueIdentifier, etechFile.getUniqueIdentifier())
                        .eq(EtechFile::getLatest, 1)
                        .ne(EtechFile::getId, etechFile.getId())
                        .set(EtechFile::getLatest, 0)
                );
            }
            //保存成功后再移动文件 改为复制文件防止事务回滚导致第二次文件找不到
            FileUtil.copy(tempFile, FileUtil.file(baseDir + path), true);
//            tempFile.delete();//删除临时文件 不再删除文件
            if (previewFile != null) {
                //保存成功后再移动预览文件  改为复制文件防止事务回滚导致第二次文件找不到
                FileUtil.copy(previewFile, FileUtil.file(baseDir + previewPath), true);
//                previewFile.delete();//删除临时文件 不再删除文件
            }
            if (etechFileTemp.getId() != null) {
                //移动成功后删除临时表
                etechFileTempService.removeById(etechFileTemp.getId());
            }
            return etechFile.getId();
        }
        return null;
    }
    /**
     * 批量移动临时文件到正式文件
     *
     * @param ids 临时文件的ids
     */
    @Transactional(rollbackFor = Exception.class)
    public void batchMoveTempFileToFormalFile(List<String> ids) {
        List<EtechFileTemp> fileList = etechFileTempService.listByIds(ids);
        if (CollUtil.isNotEmpty(fileList)) {
            for (EtechFileTemp etechFileTemp : fileList) {
                moveTempFileToFormalFile(etechFileTemp);
            }
        }
    }
    //预览文件改名处理
    private String getPreviewPath(String filePath, String previewPath){
        String baseDir = etechFileHandlerService.getEtechFileBaseDir();
        if(StringUtil.isEmpty(filePath)){
            if(StringUtil.isNotEmpty(previewPath) && !previewPath.contains("_p.")){
                File preFile = new File(baseDir + previewPath);
                String[] arr = previewPath.replaceAll("\\\\", "/").split("\\.");
                previewPath = arr[0] + "_p." + arr[1];
                FileUtil.rename(preFile, baseDir + previewPath, true);
            }
            return previewPath;
        }
        String preview = previewPath;
        String fileType = filePath.split("\\.")[1];
        String str1 = filePath.substring(0, filePath.lastIndexOf("."));
        if(StringUtil.isNotEmpty(previewPath)) {
            previewPath = previewPath.replaceAll("\\\\", "/");
            String str2 = previewPath.substring(0, previewPath.lastIndexOf("."));
            //预览文件名修改为原文件名加_p.xxx结尾
            //如果预览文件名称不符合标准，修改文件名
            if (!(str1.substring(str1.lastIndexOf(File.separator) + 1) + "_p").equals(str2.substring(str2.lastIndexOf(File.separator) + 1))) {
                String previewFileType = previewPath.split("\\.")[1];
                //预览文件名修改为原文件名加_p.xxx结尾
                File preFile = new File(baseDir + previewPath);
                if (!preFile.exists()) {
                    throw new BusinessMessage("临时文件不存在或者已删除！path=" + baseDir + previewPath);
                }
                preview = filePath.replace("." + fileType, "_p." + previewFileType);
                if(filePath.equals(previewPath)){//如果是同一个文件复制
                    FileUtil.copy(baseDir + filePath, baseDir + preview, true);
                }else {
                    FileUtil.rename(preFile, baseDir + preview, true);
                }
            }
        }
        return preview;
    }
    /**
     * 直接保存文件到正式目录
     * @param object
     * @return
     */
    public String saveEtechFile(com.alibaba.fastjson.JSONObject object) {
        EtechFile etechFile = com.alibaba.fastjson.JSONObject.toJavaObject(object, EtechFile.class);
        String baseDir = etechFileHandlerService.getEtechFileBaseDir();
        String path = etechFile.getPath();
        path = path.replaceAll("\\\\", "/");
        boolean versionsFlag = false;
        File file = new File(baseDir + path);
        if (!file.exists()) {
            throw new BusinessMessage("临时文件不存在或者已删除！path=" + path);
        }
        etechFile.setPath(path);
        if(etechFile.getId()==null){
            int index = path.lastIndexOf("/");
            etechFile.setId(path.substring(index + 1).split("\\.")[0]);
        }
        etechFile.setPreviewPath(this.getPreviewPath(path, etechFile.getPreviewPath()));
        if(StringUtil.isEmpty(etechFile.getModule())){
            etechFile.setModule("etech");
        }
        if (StringUtil.isNotEmpty(etechFile.getUniqueIdentifier()) && !etechFile.getId().equals(etechFile.getUniqueIdentifier())) {
            String sql = "select max(file_version_) version from sys_file where (delete_=0 or delete_ is null) and unique_identifier_=?";
            List<Map<String, Object>> list = DbUtil.getJdbcTemplate().queryForList(sql, etechFile.getUniqueIdentifier());
            if (CollUtil.isNotEmpty(list) && list.get(0).get("version") != null) {
                etechFile.setFileVersion(String.format("%02d", Integer.parseInt(list.get(0).get("version").toString()) + 1));
            }
            versionsFlag = true;
        }
        etechFile.setUploader("etech-web-uploader");
        int index = path.indexOf("/");
        etechFile.setYear(Integer.parseInt(path.substring(index+1, index+5)));
        if(etechFile.getFileLength()==null || etechFile.getFileLength()==0){//文件大小
            etechFile.setFileLength(file.length());
        }
        if(StringUtil.isEmpty(etechFile.getFileType())) {//文件类型
            etechFile.setFileType(path.substring(path.lastIndexOf(".") + 1));
        }
        if(StringUtil.isEmpty(etechFile.getFileVersion())){//默认版本00 唯一标识默认ID
            etechFile.setFileVersion("00");
        }
        if(StringUtil.isEmpty(etechFile.getUniqueIdentifier())){
            etechFile.setUniqueIdentifier(etechFile.getId());
        }
        if(etechFile.getCreateTime()==null){
            etechFile.setCreateTime(new Date());
        }
        if(etechFile.getCreateBy()==null){
            etechFile.setCreateBy(ContextUtil.getCurrentUserId());
        }
        if(etechFile.getUpdateTime()==null){
            etechFile.setUpdateTime(new Date());
        }
        int num = etechFileMapper.insert(etechFile);
        if (num>0 && versionsFlag) {
            etechFileMapper.update(null, Wrappers.<EtechFile>lambdaUpdate()
                    .eq(EtechFile::getUniqueIdentifier, etechFile.getUniqueIdentifier())
                    .eq(EtechFile::getLatest, 1)
                    .ne(EtechFile::getId, etechFile.getId())
                    .set(EtechFile::getLatest, 0)
            );
        }
        return num>0 ? etechFile.getId() : null;
    }
    /**
     * 更新替换文件
     * @param fileId
     * @param fileName
     * @param filePath
     * @param previewFile
     * @return
     */
    public void updateFileById(String fileId, String fileName, String filePath, String previewFile, String module){

        filePath = filePath.replaceAll("\\\\", "/");
        String baseDir = etechFileHandlerService.getEtechFileBaseDir();
        File file = new File(baseDir + filePath);//源文件
        Long fileLength = file.length();
        String fileType = filePath.split("\\.")[1];
        String str1 = filePath.substring(0, filePath.lastIndexOf("."));
        String newFilePath = filePath.replace(str1.substring(str1.lastIndexOf("/") + 1), fileId);
        FileUtil.rename(file, baseDir + newFilePath, true);//修改名称

        String previewPath = previewFile;
        if(StringUtil.isNotEmpty(previewPath) && !previewPath.contains(fileId + "_p")) {
            String str2 = previewPath.substring(0, previewPath.lastIndexOf("."));
            previewPath.replace(str2.substring(str2.lastIndexOf("/") + 1), fileId + "_p");
            File preFile = new File(baseDir + previewFile);//预览文件
            if(filePath.equals(previewFile)){//如果是同一个文件复制
                FileUtil.copy(baseDir + newFilePath, baseDir + previewPath, true);
            }else {
                FileUtil.rename(preFile, baseDir + previewPath, true);
            }
        }

        EtechFileTemp etechFileTemp = new EtechFileTemp();
        etechFileTemp.setId(fileId);
        etechFileTemp.setName(fileName);
        etechFileTemp.setPath(newFilePath);
        etechFileTemp.setPreviewPath(StringUtil.isNotEmpty(previewPath)? previewPath: "");
        etechFileTemp.setFileType(fileType);
        etechFileTemp.setFileLength(fileLength);
        etechFileTemp.setUploader("etech-web-uploader");
        etechFileTemp.setModule(module);
        etechFileTemp.setYear(Integer.parseInt(filePath.substring(filePath.indexOf("temp")+5, filePath.indexOf("temp")+9)));
        etechFileTemp.setUpdateTime(new Date());
        etechFileTemp.setUpdateBy(ContextUtil.getCurrentUserId());
        this.updateFileById(etechFileTemp);
    }

    /**
     * 更新替换文件
     * @param etechFileTemp
     * @return
     */
    private void updateFileById(EtechFileTemp etechFileTemp) {
        if (etechFileTemp == null) {
            //不存在说明已经移动过了，忽略
            return;
        }
        String baseDir = etechFileHandlerService.getEtechFileBaseDir();
        String path = etechFileTemp.getPath();
        if (!FileUtil.exist(baseDir + path)) {
            throw new BusinessMessage("临时文件不存在或者已删除！path=" + path);
        }
        EtechFile etechFile = JSONUtil.toBean(JSONUtil.toJsonStr(etechFileTemp), EtechFile.class);
        File tempFile = FileUtil.file(baseDir + path);
        if (path.startsWith("temp")) {
            path = path.replaceFirst("temp", etechFileTemp.getModule());
        }
        if(etechFile.getFileLength()==null || etechFile.getFileLength()==0){//文件大小
            etechFile.setFileLength(tempFile.length());
        }
        etechFile.setPath(path);
        String previewPath = etechFileTemp.getPreviewPath();
        File previewFile = null;
        if (StringUtil.isNotEmpty(previewPath)) {
            previewFile = FileUtil.file(baseDir + previewPath);
            if (previewPath.startsWith("temp")) {
                previewPath = previewPath.replaceFirst("temp", etechFileTemp.getModule());
            }
            etechFile.setPreviewPath(previewPath);
        }
        int num = etechFileMapper.updateById(etechFile);
        if(num>0) {
            //保存成功后再移动文件
            FileUtil.move(tempFile, FileUtil.file(baseDir + path), true);
            tempFile.delete();//删除临时文件
            //保存成功后再移动预览文件
            if(previewFile!=null) {
                FileUtil.move(previewFile, FileUtil.file(baseDir + previewPath), true);
                previewFile.delete();//删除临时文件
            }
            if(etechFileTemp.getId()!=null) {
                //移动成功后删除临时表
                etechFileTempService.removeById(etechFileTemp.getId());
            }
        }
    }
    //更新文件表
    public int updateEtechFileById(com.alibaba.fastjson.JSONObject object) {
        if(StringUtil.isEmpty(object.getString("id"))){
            return 0;
        }
        List<Object> param = new ArrayList<>();// 参数
        StringBuffer sqlBuf = new StringBuffer("update sys_file set ");
        if(object.getString("table")!=null && "sys_file_temp".equals(object.getString("table").trim())){
            sqlBuf = new StringBuffer("update sys_file_temp set ");
        }
        if(object.getString("name")!=null){
            sqlBuf.append("name_=?,");
            param.add(object.getString("name"));
        }
        if(object.getString("path")!=null){
            sqlBuf.append("path_=?,");
            param.add(object.getString("path"));
        }
        if(object.getString("module")!=null){
            sqlBuf.append("module_=?,");
            param.add(object.getString("module"));
        }
        if(object.getString("uploader")!=null){
            sqlBuf.append("uploader_=?,");
            param.add(object.getString("uploader"));
        }
        if(object.getString("previewPath")!=null){
            sqlBuf.append("preview_=?,");
            param.add(object.getString("previewPath"));
        }
        if(object.getString("uniqueIdentifier")!=null){
            sqlBuf.append("unique_identifier_=?,");
            param.add(object.getString("uniqueIdentifier"));
        }
        if(object.getInteger("year")!=null){
            sqlBuf.append("year_=?,");
            param.add(object.getInteger("year"));
        }
        if(object.getString("fileVersion")!=null){
            sqlBuf.append("file_version_=?,");
            param.add(object.getString("fileVersion"));
        }
        if(object.getInteger("latest")!=null){
            sqlBuf.append("latest_=?,");
            param.add(object.getInteger("latest"));
        }
        if(object.getInteger("delete")!=null){
            sqlBuf.append("delete_=?,");
            param.add(object.getInteger("delete"));
        }
        if(object.getString("fileType")!=null){
            sqlBuf.append("file_type_=?,");
            param.add(object.getString("fileType"));
        }
        if(object.getString("fileLength")!=null){
            sqlBuf.append("file_length=?,");
            param.add(object.getString("fileLength"));
        }
        if(param.size()>0) {
            sqlBuf.append("update_by_=").append(ContextUtil.getCurrentUserId()).append(",update_time_=now() ");
        }else {
            return 0;
        }
        param.add(object.getString("id"));
        sqlBuf.append(" where id_=?");
        return DbUtil.getJdbcTemplate().update(sqlBuf.toString(), param.toArray());
    }
    /**
     * 批量删除正式文件
     *
     * @param ids 正式文件ids
     */
    @Transactional(rollbackFor = Exception.class)
    public void batchDeleteFileByIds(List<String> ids) {
        List<EtechFile> fileList = etechFileMapper.selectBatchIds(ids);
        if (CollUtil.isNotEmpty(fileList)) {
            etechFileMapper.deleteBatchIds(ids);
            String baseDir = etechFileHandlerService.getEtechFileBaseDir();
            for (EtechFile etechFile : fileList) {
                String path = "", previewPath = "", thumbnailPath = "";
                //新的上传器
                if ("etech-web-uploader".equals(etechFile.getUploader())) {
                    if (StrUtil.isNotBlank(etechFile.getPath())) {
                        path = baseDir + etechFile.getPath();
                    }
                    if (StrUtil.isNotBlank(etechFile.getPreviewPath())) {
                        previewPath = baseDir + etechFile.getPreviewPath();
                    }
                    if (StrUtil.isNotBlank(etechFile.getThumbnailPath())) {
                        thumbnailPath = baseDir + etechFile.getThumbnailPath();
                    }
                } else {
                    //旧的上传器
                    if (StrUtil.isNotBlank(etechFile.getPath())) {
                        path = etechOrdinaryUploader.getAbsolutePath(etechFile.getPath());
                    }
                    if (StrUtil.isNotBlank(etechFile.getPreviewPath())) {
                        previewPath = etechOrdinaryUploader.getAbsolutePath(etechFile.getPreviewPath());
                    }
                    if (StrUtil.isNotBlank(etechFile.getThumbnailPath())) {
                        thumbnailPath = etechOrdinaryUploader.getAbsolutePath(etechFile.getThumbnailPath());
                    }
                }
                //上面删除使用的是逻辑删除，这里先不把实际的文件删掉，只删除预览和缩略图的文件，后面定期清理逻辑删除的数据后再删除文件，和定期清理临时文件一样
                /*if (StrUtil.isNotBlank(path) && FileUtil.exist(path)) {
                    FileUtil.del(path);
                    //todo 删除后再删除关联的日志表
                }*/
                if (StrUtil.isNotBlank(previewPath) && FileUtil.exist(previewPath)) {
                    FileUtil.del(previewPath);
                }
                if (StrUtil.isNotBlank(thumbnailPath) && FileUtil.exist(thumbnailPath)) {
                    FileUtil.del(thumbnailPath);
                }
            }
        }
    }

    /**
     * 保存表单后处理文件
     *
     * @param data
     */
    public void handlerFileAfterSaveForm(com.alibaba.fastjson.JSONObject data) {
        if (!JSONUtil.isNull(data)) {
            if (data.getJSONArray("add_file_list") != null) {
                List<String> newFileList = com.alibaba.fastjson.JSONObject.parseArray(JSONUtil.toJsonStr(data.getJSONArray("add_file_list")), String.class);
                batchMoveTempFileToFormalFile(newFileList);
            }
            if (data.getJSONArray("del_file_list") != null) {
                List<String> delFileList = com.alibaba.fastjson.JSONObject.parseArray(JSONUtil.toJsonStr(data.getJSONArray("del_file_list")), String.class);
                batchDeleteFileByIds(delFileList);
            }
        }
    }

    /**
     * 验证文件md5
     *
     * @param fileUploadDTO
     */
    public EtechFileTemp checkmd5(FileUploadDTO fileUploadDTO) {
        //先查询正式文件是否存在
        List<EtechFile> fileList = etechFileMapper.selectList(Wrappers.<EtechFile>lambdaQuery()
                .eq(EtechFile::getMd5, fileUploadDTO.getMd5())
                .orderByDesc(EtechFile::getCreateTime));
        boolean isExist = false;
        String oldFilePath = "";
        if (CollUtil.isNotEmpty(fileList)) {
            for (EtechFile etechFile : fileList) {
                if (etechFile.isWebUploader()) {
                    oldFilePath = etechFileHandlerService.getAbsolutePath(etechFile.getPath());
                } else {
                    oldFilePath = etechOrdinaryUploader.getAbsolutePath(etechFile.getPath());
                }
                if (StrUtil.isNotBlank(oldFilePath) && FileUtil.exist(etechFileHandlerService.getAbsolutePath(oldFilePath))) {
                    isExist = true;
                    break;
                }
            }
        }
        if (!isExist) {
            List<EtechFileTemp> tempFileList = etechFileTempService.list(Wrappers.<EtechFileTemp>lambdaQuery()
                    .eq(EtechFileTemp::getMd5, fileUploadDTO.getMd5())
                    .orderByDesc(EtechFileTemp::getCreateTime));
            if (CollUtil.isNotEmpty(tempFileList)) {
                for (EtechFileTemp etechFileTemp : tempFileList) {
                    oldFilePath = etechFileHandlerService.getAbsolutePath(etechFileTemp.getPath());
                    if (StrUtil.isNotBlank(oldFilePath) && FileUtil.exist(etechFileHandlerService.getAbsolutePath(oldFilePath))) {
                        isExist = true;
                        break;
                    }
                }
            }
        }
        if (isExist) {
            String id = IdUtil.getSuid();
            String tempPath = etechFileHandlerService.getTempFileRelativePath(id + "." + FileUtil.extName(fileUploadDTO.getName()));
            //复制文件到临时文件
            FileUtil.copy(etechFileHandlerService.getAbsolutePath(oldFilePath),
                    etechFileHandlerService.getAbsolutePath(tempPath),
                    true);
            //生成新的临时文件表
            return saveTempFile(id, tempPath, fileUploadDTO);
        }
        return null;
    }
    //根据路径删除文件
    public void deleteFile(String path){
        if(StringUtil.isNotEmpty(path)) {
            String baseDir = etechFileHandlerService.getEtechFileBaseDir(path);
            File file = new File(baseDir + path);
            if(file.exists()){
                FileUtil.del(file);
            }
        }
    }
    /**
     * 删除文件
     * @param fileId
     * @param removeFile
     * @return
     */
    public int deleteFile(String fileId, boolean removeFile){
        int num = 0;
        if(removeFile){
            EtechFile etechFile = etechFileMapper.selectById(fileId);
            if(etechFile!=null) {
                String baseDir = etechFileHandlerService.getEtechFileBaseDir();
                FileUtil.del(new File(baseDir + etechFile.getPath()));
                if (StringUtil.isNotEmpty(etechFile.getPreviewPath())) {
                    FileUtil.del(new File(baseDir + etechFile.getPreviewPath()));
                }
                if (StringUtil.isNotEmpty(etechFile.getThumbnailPath())) {
                    FileUtil.del(new File(baseDir + etechFile.getThumbnailPath()));
                }
                DbUtil.getJdbcTemplate().update("delete from sys_file where id_=?", fileId);
                DbUtil.getJdbcTemplate().update("delete from sys_file_log where file_id_=?", fileId);
            }
        }else {
            /*EtechFile etechFile = new EtechFile();
            etechFile.setId(fileId);
            etechFile.setDelete(true);
            num = etechFileMapper.updateById(etechFile);*/
            String sql = "update sys_file set delete_=0 where id_=?";
            DbUtil.getJdbcTemplate().update(sql, fileId);
        }
        return num;
    }
    //超管替换
    public String superReplace(String fileid2,String fileid1,Boolean isPreview){
        EtechFile file1 = etechFileMapper.selectById(fileid1);//原始文件
        EtechFileTemp file2 = etechFileTempService.getById(fileid2);//替换文件
        if (isPreview){
            //如果是预览文件则判断其后缀是否与原来相同
            String substring = file1.getPreviewPath().substring(file1.getPreviewPath().lastIndexOf(".") + 1);
            String file2Name = file2.getName();
            String substring2 = file2Name.substring(file2Name.lastIndexOf(".") + 1);
            if (!substring.equals(substring2)){
                return "请确认替换预览文件格式";
            }
        }

        String baseDir = etechFileHandlerService.getEtechFileBaseDir();
        try {
            if (!isPreview){
            String substring = file1.getPath().substring(file1.getPath().lastIndexOf(".") + 1);
            String file2Name = file2.getName();
            String substring2 = file2Name.substring(file2Name.lastIndexOf(".") + 1);
            String replace = file1.getPath();
            if (!substring.equals(substring2)){
                replace = file1.getPath().replace(substring, substring2);
            }
            copyFile(baseDir+replace,baseDir+file2.getPath());
            if (!substring.equals(substring2)) {
                //如果文件格式变化，替换后物理删除源文件及更改其路径信息及文件名信息
                IUploader uploader1 = UploaderFactory.getUploader(file1.getUploader());
                uploader1.remove(file1.getPath());
                file1.setPath(replace);
                String replace1 = file1.getName().replace(file1.getName().substring(file1.getName().lastIndexOf(".") + 1), substring2);
                file1.setName(replace1);
                etechFileMapper.updateById(file1);
            }
                //如果不是预览文件则删除原有预览文件并添加到转换队列
//                IUploader uploader = UploaderFactory.getUploader(file1.getUploader());
//                uploader.remove(file1.getPreviewPath());
//                etechFileService.rePreview(fileid2,"drawing");
            }else {
                String replace = file1.getPreviewPath();
                copyFile(baseDir+replace,baseDir+file2.getPath());
            }

        } catch (Exception e) {
            e.printStackTrace();
            return "error";
        }
        return "success";
    }
    private void copyFile(String oldPath,String newPath)throws Exception {
        //获取要复制的文件
        File oldfile=new File(newPath);
        //文件输入流，用于读取要复制的文件
        FileInputStream fileInputStream = new FileInputStream(oldfile);
        //要复制过去的文件
        File newfile=new File(oldPath);
        //获取父目录
        File fileParent = newfile.getParentFile();
        System.out.println(fileParent);
        //判断是否存在
        if (!fileParent.exists()) {
            // 创建父目录文件夹
            fileParent.mkdirs();
        }
        //判断文件是否存在
        if (!newfile.exists()) {
            //创建文件
            newfile.createNewFile();
        }
        //新文件输出流
        FileOutputStream fileOutputStream = new FileOutputStream (newfile);
        byte[] buffer= new byte[1024];
        int len;
        //将文件流信息读取文件缓存区，如果读取结果不为-1就代表文件没有读取完毕，反之已经读取完毕
        while ((len=fileInputStream.read(buffer))!=-1) {
            fileOutputStream.write(buffer, 0, len);
            fileOutputStream.flush();
        }
        fileInputStream.close();
        fileOutputStream.close();
    }

    /**
     * 删除临时文件
     * @param fileId
     * @return
     */
    public boolean deleteTempFile(String fileId){
        EtechFileTemp etechFileTemp = etechFileTempService.getById(fileId);
        if(etechFileTemp==null) {
            return true;
        }
        String baseDir = etechFileHandlerService.getEtechFileBaseDir();
        if(StringUtil.isNotEmpty(etechFileTemp.getPath())) {
            new File(baseDir + etechFileTemp.getPath()).delete();
        }
        if(StringUtil.isNotEmpty(etechFileTemp.getPreviewPath())) {
            new File(baseDir + etechFileTemp.getPreviewPath()).delete();
        }
        if(StringUtil.isNotEmpty(etechFileTemp.getThumbnailPath())) {
            new File(baseDir + etechFileTemp.getThumbnailPath()).delete();
        }
        return etechFileTempService.removeById(fileId);
    }

    //替换文件
    public void replaceFile(String fileId, String newFileId, String newPreviewFileId){
        EtechFile file = etechFileMapper.selectById(fileId);
        EtechFileTemp newFileTemp = null;
        EtechFileTemp newPreviewFile = null;
        com.alibaba.fastjson.JSONObject object = new com.alibaba.fastjson.JSONObject();
        object.put("id", file.getId());
        if(StringUtil.isNotEmpty(newFileId)){//原文件替换
            newFileTemp = etechFileTempService.getById(newFileId);
            object.put("name", newFileTemp.getName());
            object.put("fileType", newFileTemp.getFileType());
            object.put("fileLength", newFileTemp.getFileLength());
            object.put("path", file.getPath().substring(0, file.getPath().lastIndexOf(".")+1) + newFileTemp.getFileType());
            //移动文件
            this.moveTempFileOnly(newFileTemp.getId(), newFileTemp.getPath(), object.getString("path"));
        }
        if(StringUtil.isNotEmpty(newPreviewFileId)){//预览文件替换
            newPreviewFile = etechFileTempService.getById(newPreviewFileId);
            object.put("previewPath", file.getPath().substring(0, file.getPath().lastIndexOf(".")) + "_p." + newPreviewFile.getFileType());
            //移动文件
            this.moveTempFileOnly(newPreviewFile.getId(), newPreviewFile.getPath(), object.getString("previewPath"));
        }else if(StringUtil.isNotEmpty(newFileId)) {
            object.put("previewPath", "");
        }
        this.updateEtechFileById(object);
    }
}
